package com.lidy.tankbattle.tankgame2.bullet;

import com.lidy.tankbattle.tankgame2.bomb.Bomb;
import com.lidy.tankbattle.tankgame2.constant.TankPriorities;
import com.lidy.tankbattle.tankgame2.constant.WallPriorities;
import com.lidy.tankbattle.tankgame2.tank.EnemyTank;
import com.lidy.tankbattle.tankgame2.tank.EntityLocation;
import com.lidy.tankbattle.tankgame2.tank.Hero;
import com.lidy.tankbattle.tankgame2.tank.Tank;
import com.lidy.tankbattle.tankgame2.wall.Wall;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lidy
 * @version V1.0
 * @classname BulletDetection
 * @description 子弹是否撞击墙壁、坦克、边界检测
 * @date 2022/6/7 20:32
 */
public class BulletDetection {
    /**
     * @author: lidy
     * @description: 更新子弹状态
     * @date: 2022/6/3 18:12
     */
    public static void detectBulletsResult(Hero hero, ConcurrentHashMap<Integer, EnemyTank> enemyTanks,
                                           ConcurrentHashMap<Integer, Wall> walls, ConcurrentHashMap<Integer, Bomb> bombs,
                                           ConcurrentHashMap<Integer, EntityLocation> tanksLocations) {
        // 敌方子弹是否击中我方坦克或墙体判断
        enemyTanks.forEach((number, enemyTank) -> {
            if (enemyTank.getLive()) {
                enemyTank.getBullets().forEach((bullet, fromTankNumber) -> {
                    if (bullet.getLive()) {
                        for (Map.Entry<Integer, Wall> wallEntry : walls.entrySet()) {
                            Wall wall = wallEntry.getValue();
                            bulletHitWall(bullet, wall, bombs);
                            if (!bullet.getLive()) {
                                break;
                            }
                        }
                        if (bullet.getLive() && hero.getLive() && !hero.getInvincible()) {
                            bulletHitTank(bullet, hero, bombs);
                            if (!hero.getLive()) {
                                bombs.put(hero.getNumber(), Bomb.getTankBomb(hero.getX(), hero.getY()));
                                tanksLocations.remove(TankPriorities.MY_TANK_NUMBER);
                            }
                        }
                    }
                    if (!bullet.getLive()) {
                        enemyTank.getBullets().remove(bullet);
                    }
                });
            }
        });

        // 我方子弹是否击中敌方坦克或墙体判断
        hero.getBullets().forEach((bullet, fromTankNumber) -> {
            if (bullet.getLive()) {
                for (Map.Entry<Integer, EnemyTank> tankEntry : enemyTanks.entrySet()) {
                    EnemyTank tank = tankEntry.getValue();
                    if (tank.getLive() && !tank.getInvincible()) {
                        bulletHitTank(bullet, tank, bombs);
                        if (!bullet.getLive()) {
                            break;
                        }
                    }
                }
                if (bullet.getLive()) {
                    for (Map.Entry<Integer, Wall> wallEntry : walls.entrySet()) {
                        bulletHitWall(bullet, wallEntry.getValue(), bombs);
                    }
                }
            }
            if (!bullet.getLive()) {
                hero.getBullets().remove(bullet);
            }
        });

    }

    /**
     * @author: lidy
     * @description: 子弹是否击中墙体判断
     * @date: 2022/6/7 20:31
     */
    private static void bulletHitWall(Bullet bullet, Wall wall, ConcurrentHashMap<Integer, Bomb> bombs) {
        if (bullet.getLive() && wall.getExist()) {
            if (bullet.getX() >= wall.getX() && bullet.getX() <= (wall.getX() + wall.getWidth()) && bullet.getY() >= wall.getY() && bullet.getY() <= (wall.getY()) + wall.getHeight()) {
                bullet.setLive(false);
                if (wall.getType() == WallPriorities.BRICK_WALL) {
                    wall.reduceBlood(bullet.getPower());
                }
                if (!wall.getExist()) {
                    bombs.put(wall.getNumber(), Bomb.getWallBomb(wall.getX(), wall.getY()));
                }
            }
        }
    }

    /**
     * @author: lidy
     * @description: 子弹是否击中坦克判断
     * @date: 2022/6/2 9:58
     */
    private static void bulletHitTank(Bullet bullet, Tank tank, ConcurrentHashMap<Integer, Bomb> bombs) {
        if (bullet.getLive() && tank.getLive() && bullet.getFromTankNumber() != tank.getNumber()) {
            int tankLeftX = tank.getX(), tankUpY = tank.getY(), tankRightX, tankDownY;
            switch (tank.getDirection()) {
                case TankPriorities.DIRECTION_UP, TankPriorities.DIRECTION_DOWN -> {
                    tankRightX = tankLeftX + tank.getWidth();
                    tankDownY = tankUpY + tank.getHeight();
                }
                default -> {
                    tankRightX = tankLeftX + tank.getHeight();
                    tankDownY = tankUpY + tank.getWidth();
                }
            }
            if (bullet.getX() > tankLeftX && bullet.getX() < tankRightX && bullet.getY() > tankUpY && bullet.getY() < tankDownY) {
                bullet.setLive(false);
                tank.reduceBlood(bullet.getPower());
                if (!tank.getLive()) {
                    // 添加炸弹
                    bombs.put(tank.getNumber(), Bomb.getTankBomb(tank.getX(), tank.getY()));
                }
            }
        }
    }
}
